package com.ecommerce.filter;

import com.ecommerce.constant.CommonConstant;
import com.ecommerce.util.TokenParseUtil;
import com.ecommerce.vo.LoginUserInfo;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Component;
import org.springframework.web.servlet.HandlerInterceptor;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

/**
 * 用户身份统一登录拦截
 */
@SuppressWarnings("all")
@Slf4j
@Component
public class LoginUserInfoInterceptor implements HandlerInterceptor {

    @Override
    public boolean preHandle(
            HttpServletRequest request,
            HttpServletResponse response,
            Object handler
    ) throws Exception {
        if (checkWhiteListUrl(request.getRequestURI())) {
            return true;
        }

        // 先尝试从http header里拿到token
        String token = request.getHeader(CommonConstant.JWT_USER_INFO_KEY);
        LoginUserInfo loginUserInfo = null;
        try {
            loginUserInfo = TokenParseUtil.parseUserInfoFromToken(token);
        }catch (Exception exception) {
            log.error("parse login user info error: [{}]", exception.getMessage(), exception);
        }

        // 如果程序走到这里，说明 header 中没有token信息
        // 网关已经有了这一步操作，此处仅示意该功能
        log.info("debug: " + request.getRequestURI());
        if (loginUserInfo == null) {
            throw new RuntimeException("can not parse current login user");
        }

        // 设置请求上下文，把用户信息填充进去
        AccessContext.setLoginUserInfo(loginUserInfo);

        return true;
    }

    /**
     * 在请求完全结束后调用, 常用于清理资源, 统计请求耗时【不推荐】等等
     */
    @Override
    public void afterCompletion(
            HttpServletRequest request,
            HttpServletResponse response,
            Object handler,
            Exception ex
    ) throws Exception {
        if (AccessContext.getLoginUserInfo() != null) {
            AccessContext.clearLoginUserInfo();
        }
    }

    /**
     * 设置白名单
     */
    private boolean checkWhiteListUrl(String url) {
        return StringUtils.containsAny(
                url,
                "springfox", "swagger", "v2",
                "webjars", "doc.html"
        );
    }
}
